package com.tarena.lbs.business.servcie.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tarena.lbs.attach.api.AttachApi;
import com.tarena.lbs.attach.pojo.param.PicUpdateParam;
import com.tarena.lbs.base.common.utils.Asserts;
import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.base.protocol.pager.PageResult;
import com.tarena.lbs.business.dao.repository.BusinessRepository;
import com.tarena.lbs.business.pojo.param.BusinessParam;
import com.tarena.lbs.business.pojo.po.BusinessPO;
import com.tarena.lbs.business.pojo.query.BusinessQuery;
import com.tarena.lbs.business.pojo.vo.BusinessStoreVO;
import com.tarena.lbs.business.pojo.vo.BusinessVO;
import com.tarena.lbs.business.servcie.BusinessService;
import com.tarena.lbs.common.enums.Roles;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.common.utils.AuthenticationContextUtils;
import com.tarena.lbs.user.api.UserApi;
import com.tarena.lbs.user.api.pojo.dto.AdminDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.rpc.RpcException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class BusinessServiceImpl implements BusinessService {
    @Autowired
    private BusinessRepository businessRepository;
    @DubboReference(retries = 5)
    private UserApi userApi;
    @DubboReference(retries = 5)
    private AttachApi attachApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(BusinessParam param)throws BusinessException {
        //1.获取解析的认证对象 判断用户权限
        checkRole(Roles.ADMIN);
        //2.封装数据新增 保证新增幂等
        Integer id=saveOnce(param);
        //3.绑定图片
        bindPictures(param,id);
    }
    private void bindPictures(BusinessParam param,Integer businessId) throws BusinessException {
        //1.封装入参 2张图片 licenseUrl logoUrl 同一个商家businessId 100 200
        List<PicUpdateParam> params=new ArrayList<>();
        //1.1封装一个绑定营业执照
        PicUpdateParam license=new PicUpdateParam();
        license.setBusinessId(businessId);
        license.setBusinessType(100);
        //licenseUrl=http://localhost:9081/static/2932e9fn23fh923fj023fj.png
        license.setFileUuid(parseFileUuid(param.getBusinessLicense()));
        params.add(license);
        //1.2封装一个绑定商家logo
        PicUpdateParam logo=new PicUpdateParam();
        logo.setBusinessId(businessId);
        logo.setBusinessType(200);
        //licenseUrl=http://localhost:9081/static/2932e9fn23fh923fj023fj.png
        logo.setFileUuid(parseFileUuid(param.getBusinessLogo()));
        params.add(logo);
        //2.调用接口
        try{
            boolean result = attachApi.batchUpdateBusiness(params);
            if (!result){
                throw new BusinessException("-2","图片绑定业务失败");
            }
        }catch (RpcException e){
            //将新增商家回滚
            throw new BusinessException("-2","图片绑定调用失败");
        } catch (BusinessException e) {
            throw new RuntimeException(e);
        }

    }
    private String parseFileUuid(String businessLicense) {
        return businessLicense.split("/")[4];
    }

    private Integer saveOnce(BusinessParam param) throws BusinessException {
        //幂等设计 不能出现同一个商家名称 多次
        //利用 入参的商家名称 查询已有的商家数据数量
        checkBusinessCount(param.getBusinessName());
        //param表单入参类型 并不一定和po 和表格一一对象不能直接写入数据库 转化po并且补齐数据
        BusinessPO poParam=new BusinessPO();
        BeanUtils.copyProperties(param,poParam);
        //entryTime
        poParam.setEntryTime(new Date());
        //审核意见非空 同意
        poParam.setAuditRemarks("同意");
        //商家状态非空 1
        poParam.setBusinessStatus(1);
        //调用仓储层新增 mybatis 具备一个能力 给po对象的主键属性 回填数据
        businessRepository.save(poParam);
        return poParam.getId();
    }

    private void checkBusinessCount(String businessName) throws BusinessException {
        //select count(0) from lbs_business where business_name=?
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("business_name",businessName);
        long count = businessRepository.count(queryWrapper);
        Asserts.isTrue(count>0,new BusinessException("-2","商家名称重复"));
    }

    private void checkRole(Roles role) throws BusinessException {
        //线程下游 拿到认证对象
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        //如果认证解析有问题 拿到的是null
        Asserts.isTrue(userPrinciple==null,
                new BusinessException("-2","用户认证解析失败"));
        //如果和要求的角色不同 说明没有符合业务权限
        Asserts.isTrue(userPrinciple.getRole()!=role,
                new BusinessException("-2","用户权限不足"));
    }

    @Override
    public PageResult<BusinessVO> pageList(BusinessQuery query) throws BusinessException {
        log.debug("业务层query:{}",query);
        PageResult<BusinessVO> voPage=new PageResult<>(query);
        PageInfo pageInfo = getPageResult(query);
        voPage.setTotal(pageInfo.getTotal());
        List<BusinessPO> pos = pageInfo.getList();
        List<BusinessVO> vos=null;
        if (pos!=null&&pos.size()>0){
            vos=pos.stream().map(po->{
                BusinessVO vo=new BusinessVO();
                BeanUtils.copyProperties(po,vo);
                return vo;
            }).collect(Collectors.toList());
        }
        voPage.setObjects(vos);
        log.debug("业务层返回:{}",voPage);
        return voPage;
    }

    private PageInfo getPageResult(BusinessQuery businessQurey) throws BusinessException {
        //组织 查询的业务条件
        Integer businessId = checkAndGetBusinessId();
        QueryWrapper<BusinessPO> queryWrapper;
        if (businessId!=null){
            queryWrapper=new QueryWrapper<>();
            queryWrapper.eq("id", businessId);
        } else  if (businessQurey.getBusinessName() != null && !businessQurey.getBusinessName().isEmpty()) {
            queryWrapper=new QueryWrapper<>();
            queryWrapper.eq("business_name", businessQurey.getBusinessName());
        }else if (businessQurey.getBusinessStatus() != null) {
            queryWrapper=new QueryWrapper<>();
            queryWrapper.eq("business_status", businessQurey.getBusinessStatus());
        }else if (businessQurey.getStartingTime() != null && businessQurey.getEndTime() != null) {
            queryWrapper=new QueryWrapper<>();
            queryWrapper.between("entry_time", businessQurey.getStartingTime(), businessQurey.getEndTime());
        } else if (businessQurey.getStartingTime() != null) {
            queryWrapper=new QueryWrapper<>();
            queryWrapper.ge("entry_time", businessQurey.getStartingTime());
        } else if (businessQurey.getEndTime() != null) {
            queryWrapper=new QueryWrapper<>();
            queryWrapper.le("entry_time", businessQurey.getEndTime());
        }
        else{
            queryWrapper= Wrappers.emptyWrapper();
        }
        PageHelper.startPage(businessQurey.getPageNo(),businessQurey.getPageSize());
        List<BusinessPO> pos = businessRepository.list(queryWrapper);
        log.info("分页插件开启,pos类型为:{}",pos.getClass().getName());
        //封装pageInfo对象
        PageInfo pageInfo=new PageInfo<>(pos);
        return pageInfo;
    }

    private Integer checkAndGetBusinessId() throws BusinessException {
        //1.拿到认证对象
        UserPrinciple userPrinciple = AuthenticationContextUtils.get();
        //2.断言空
        Asserts.isTrue(userPrinciple==null,new BusinessException("-2","用户认证解析失败"));
        //3.拿到角色
        Roles role = userPrinciple.getRole();
        Integer businessId=null;
        //4.如果角色是SHOP 需要给businessId赋值
        AdminDto adminDto = userApi.getAdminById(userPrinciple.getId());
        if (role==Roles.SHOP){
            businessId=adminDto.getBusinessId();
        }
        return businessId;
    }
    @Override
    public BusinessStoreVO detail(Integer businessId) {
        BusinessPO po = businessRepository.selectById(businessId);
        BusinessStoreVO vo = new BusinessStoreVO();
        BeanUtils.copyProperties(po,vo);
        return vo;
    }

    @Override
    public void update(BusinessParam param) {

    }

}
